package com.jcroke.hercules.examples;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public abstract class Datum extends DatumFunction {
	protected Object value;
	protected Class<?> type;

	public Datum(Class<?> type) throws DatumException {
		this(type, "");
	}

	public Datum(Class<?> type, Object val) throws DatumException {
		this.type = type;
		this.setValue(val);
	}

	public Object getValue() {
		return value;
	}

	public void setValue(Object val) throws DatumException {
		Class<?> cpc = getPrimitiveOfType(val);
		Constructor<?> cstrctr;
		try {
			cstrctr = type.getConstructor(cpc);
		} catch (SecurityException e) {
			throw new DatumException("Datum Constructor for "
					+ type.getCanonicalName(), e.getMessage());
		} catch (NoSuchMethodException e) {
			throw new DatumException("Datum Constructor for "
					+ type.getCanonicalName(), e.getMessage());
		}

		try {
			this.value = cstrctr.newInstance(val);
		} catch (IllegalArgumentException e) {
			throw new DatumException("Datum Constructor for "
					+ type.getCanonicalName(), e.getMessage());
		} catch (InstantiationException e) {
			throw new DatumException("Datum Constructor for "
					+ type.getCanonicalName(), e.getMessage());
		} catch (IllegalAccessException e) {
			throw new DatumException("Datum Constructor for "
					+ type.getCanonicalName(), e.getMessage());
		} catch (InvocationTargetException e) {
			throw new DatumException("Datum Constructor for "
					+ type.getCanonicalName(), e.getMessage());
		}
	}

	public final Class<?> getPrimitiveOfType(Object val) {
		// For use in constructor location of java.Lang types; find primitive of
		// the wrapper class.
		Class<?> constructorPrimitiveClass;

		if (val.getClass().getSimpleName().equals("Integer")) {
			constructorPrimitiveClass = int.class;
		} else if (val.getClass().getSimpleName().equals("Double")) {
			constructorPrimitiveClass = double.class;
		} else if (val.getClass().getSimpleName().equals("Long")) {
			constructorPrimitiveClass = long.class;
		} else if (val.getClass().getSimpleName().equals("Float")) {
			constructorPrimitiveClass = float.class;
		} else if (val.getClass().getSimpleName().equals("Boolean")) {
			constructorPrimitiveClass = boolean.class;
		} else if (val.getClass().getSimpleName().equals("Short")) {
			constructorPrimitiveClass = short.class;
		} else if (val.getClass().getSimpleName().equals("Byte")) {
			constructorPrimitiveClass = byte.class;
		} else {
			constructorPrimitiveClass = val.getClass();
		}
		return constructorPrimitiveClass;
	}

	public String toString() {
		return value.toString();
	}
}